#!/bin/bash

set -eu

source $SNAP/actions/common/utils.sh

KUBECTL="$SNAP/kubectl --kubeconfig=${SNAP_DATA}/credentials/client.config"


usage() {
  cat<<EOF
Usage: ${SNAP_NAME} [OPTIONS...]

Options:
  -h, --help                 give this help list
  --destroy-storage          Also destroy storage
EOF
}

disable_addons() {
  echo "Disabling all addons."
  actions="$(get_all_addons)"
  for action in $actions; do
    if [ "$action" = "ha-cluster" ]
    then
      continue
    fi
    echo "Disabling addon : $action"
    addon_arguments=""
    if [ "$action" = "storage" ] && [ ${destroy_storage_enabled} ]
    then
       microk8s disable $action:destroy-storage > /dev/null 2>&1 || true
    else
       microk8s disable $action > /dev/null 2>&1 || true
    fi
  done

  # Wait for 60 secs at most.
  echo "Waiting for kubernetes resources to be released"
  n=0
  until [ $n -ge 3 ]
  do
    ($KUBECTL get po --all-namespaces 2>&1 | grep "No resources found" 2>&1 > /dev/null) && break
    n=$[$n+1]
    sleep 20
  done
  echo "All addons disabled."
}

clean_cluster() {
  echo "Calling clean_cluster"
  # Clean the cluster

  NSES=$($KUBECTL get ns -o=name | awk -F/ '{print $2}' | paste -s --delimiters=' ')
  for NS in $NSES
  do
    echo "Cleaning resources in namespace $NS"
    # we remove first resources that are automatically recreated so we do not risk race conditions
    # during which a deployment for example is recreated while any tokens are missing
    # delete all replicationcontrollers
    $KUBECTL delete --all replicationcontrollers --namespace="$NS"  --timeout=60s ||true
    # delete all daemonsets
    $KUBECTL delete --all daemonsets --namespace="$NS" --timeout=60s ||true
    # delete all deployments
    $KUBECTL delete --all deployments --namespace="$NS" --timeout=60s ||true

    # Remove all resource types except the standard k8s apiservices themselves
    $KUBECTL delete --all $($KUBECTL api-resources -o name --verbs=delete --namespaced=true | grep -v '^apiservices$' | paste -s --delimiters=',') --namespace="$NS" --timeout=60s ||true
  done

  echo "Removing CRDs"
  $KUBECTL delete --all customresourcedefinitions.apiextensions.k8s.io --timeout=60s ||true

  echo "Removing PriorityClasses"
  REMOVEABLE_PCS=$($KUBECTL get priorityclasses -o=name | awk -F/ '{if ($2 !~ /^(system-cluster-critical|system-node-critical)$/) print}' | paste -s --delimiters=' ')
  if [ -n "$REMOVEABLE_PCS" ]
  then
    $KUBECTL delete $REMOVEABLE_PCS --timeout=60s ||true
  fi

  echo "Removing StorageClasses"
  REMOVEABLE_SCS=$($KUBECTL get storageclasses -o=name | awk -F/ '{if ($2 !~ /^(microk8s-hostpath)$/) print}' | paste -s --delimiters=' ')
  if [ -n "$REMOVEABLE_SCS" ]
  then
    $KUBECTL delete $REMOVEABLE_SCS --timeout=60s ||true
  fi

  # Finally clean up the namespaces
  REMOVEABLE_NSES=$($KUBECTL get ns -o=name | awk -F/ '{if ($2 !~ /^(default|kube-public|kube-system|kube-node-lease)$/) print}' | paste -s --delimiters=' ')
  if [ -n "$REMOVEABLE_NSES" ]
  then
    $KUBECTL delete $REMOVEABLE_NSES --timeout=60s ||true
  fi

  ${SNAP}/microk8s-stop.wrapper
  sleep 5
  ${SNAP}/microk8s-start.wrapper

  # Wait for 30 secs at most.
  echo "Waiting for kubernetes resources to be released"
  n=0
  until [ $n -ge 3 ]
  do
    ($KUBECTL get po --all-namespaces 2>&1 | grep "No resources found" 2>&1 > /dev/null) && break
    n=$[$n+1]
    sleep 10
  done

  echo "Cleaning up addons client binaries.."
  if [ -d "$SNAP_DATA/bin/" ]
  then
    run_with_sudo rm -rf "$SNAP_DATA/bin/"
  fi

  if [ -e "${SNAP_DATA}/var/lock/no-cert-reissue" ]
  then
    run_with_sudo rm -rf "${SNAP_DATA}/var/lock/no-cert-reissue"
  fi
}

apply_cni() {
  if [ -e "${SNAP_DATA}/args/cni-network/cni.yaml" ]
  then
    echo "Setting up the CNI"
    $KUBECTL apply -f "${SNAP_DATA}/args/cni-network/cni.yaml"
  fi
}

clear_cni() {
  if [ -e "${SNAP_DATA}/args/cni-network/cni.yaml" ]
  then
    echo "Deleting CNI"
    $KUBECTL delete -f "${SNAP_DATA}/args/cni-network/cni.yaml" || true
  fi
}

if [ -e ${SNAP_DATA}/var/lock/clustered.lock ]
then
  echo "This MicroK8s deployment is acting as a node in a cluster."
  echo "Please remove the node before calling reset."
  exit 0
fi

NODES_NUM=$($KUBECTL get no -o name | wc -l)
if [ $NODES_NUM -ge 2 ]
then
  echo "This is a multi-node MicroK8s deployment. Reset is applicable for single node clusters."
  echo "Please remove all joined nodes before calling reset."
  exit 0
fi


destroy_storage_enabled=false
while getopts ':h-:' opt; do
  case $opt in
    -)
      case "${OPTARG}" in
        help)
          usage
          exit 0
          ;;
        destroy-storage)
          destroy_storage_enabled=true
          ;;
        *)
          echo "Invalid option --${OPTARG}" >&2
          echo "Try '${SNAP_NAME} --help' for more information."
          exit 2
          ;;
      esac
      ;;
    h)
      usage
      exit 0
      ;;
    \?)
      echo "Invalid option -${OPTARG}" >&2
      echo "Try '${SNAP_NAME} --help' for more information."
      exit 2
      ;;

  esac
done

# Fail if there are parameters we do not expect
if [ $(( $# - $OPTIND )) -ge 0 ]; then
  echo "Invalid parameter" >&2
  echo "Try '${SNAP_NAME} --help' for more information."
  exit 2
fi

exit_if_stopped
exit_if_no_permissions

disable_addons
clear_cni
clean_cluster

apply_cni
